<template>
  <el-drawer
    class="reset-drawer"
    :visible="showVisible"
    direction="rtl"
    :close-on-press-escape="false"
    :wrapperClosable="false"
    size="90%"
    :append-to-body="true"
    :destroy-on-close="true"
    :show-close="false"
  >
    <div class="b g3 f16 tl" slot="title">
      <div class="ks-row-between ks-row-middle">
        <span> 逻辑编排 </span>
        <span>
          <el-button
            type="text"
            style="vertical-align: top; margin-right: 10px"
            @click="showCode"
          >
            <span class="iconfont icondaima poi"></span>
            查看代码</el-button
          >
          <el-button
            type="text"
            size="small"
            style="margin-right: 10px"
            @click="changeShowGlobal(true)"
          >
            <div class="ks-row-middle">
              <i class="el-icon-setting f18"></i>
              <span>全局配置</span>
            </div>
          </el-button>
          <el-button size="small" type="text" @click="handleSave">
            <div class="ks-row-middle">
              <i class="el-icon-upload f18"></i>
              <span>保存</span>
            </div>
          </el-button>
          <el-button size="small" type="text" @click="handleCancel">
            <div class="ks-row-middle">
              <i class="el-icon-switch-button f18"></i>
              <span>关闭</span>
            </div>
          </el-button>
        </span>
      </div>
    </div>
    <el-container class="process-design-wrap" v-loading="loading">
      <!-- 左侧的设置区域 -->
      <div style="width: calc(100% - 1px)" class="ks-row">
        <BlocklyComponent
          class="ks-col"
          id="blockly"
          v-if="showVisible"
          :options="options"
          :eventItem="eventItem"
          ref="blocklyComponent"
          @setRightModelBlock="setRightModelBlock"
          @setShowGlobal="changeShowGlobal(true)"
        ></BlocklyComponent>
        <!-- 右侧代码展示 -->

        <div class="flexcell">
          <rightModel
            ref="rightModel"
            :componentItem="componentItem"
            :showGlobal="showGlobal"
            :eventItem="eventItem"
            :workspace="workspace"
            :block="currentBlock"
            :label="rightLabel"
            @updateShowGlobal="updateShowGlobal"
          />
        </div>
      </div>
      <div v-if="showCodeContainer" id="code">
        <el-button
          class="r"
          style="margin-right: 10px"
          type="text"
          @click="closeCode"
        >
          <div class="ks-row-middle">
            <i class="el-icon-close f20"></i>
          </div>
        </el-button>
        <el-button size="small" type="primary" @click="showCode()"
          >展示 JavaScript</el-button
        >
        <el-button size="small" type="primary" @click="showXml()"
          >展示 Xml</el-button
        >
        <pre v-show="displayCode" v-html="code"></pre>
        <pre v-show="displayXml" v-text="xml"></pre>
      </div>
    </el-container>

    <div slot="footer" class="tr">
      <el-button @click="showVisible = false">取 消</el-button>
      <el-button type="primary" @click="submit">确 定</el-button>
    </div>
  </el-drawer>
</template>

<script>
import BlocklyComponent from "./components/BlocklyComponent.vue";
import rightModel from "./components/rightModel/index";
import "./blocks/custom";
import "./blocks/present";
import "./blocks/modal";
import "./blocks/form";
import "./blocks/table";
import "./blocks/callback";
import "./blocks/request";
import "./blocks/selectComponent";
import "./blocks/router";
import "./blocks/console";
import "./blocks/function";
import "./blocks/context";
import "./blocks/requestStream";
import "./blocks/object";
import "./blocks/loop";
import "./blocks/component";
import "./blocks/promise";
import "./blocks/moment";
import "./blocks/list";
import "./blocks/common";
import "./blocks/confirm";
import "./prompt";

import BlocklyJS from "blockly/javascript";
import Blockly from "blockly";
import { mapGetters } from "vuex";
import { uuid } from "@/utils/common.js";
import { desigconfig } from "@/pageConfig/index.js";

export default {
  name: "Blockly",
  components: {
    BlocklyComponent,
    rightModel,
  },
  computed: {
    ...mapGetters([
      "getFormData",
      "getFormList",
      "getTemplateDate",
      "getFormListInTree",
      "getModelTreeList",
      "getFormDataForMain",
    ]),
  },
  data() {
    return {
      uuid,
      desigconfig,
      showGlobal: true,
      workspace: {},
      eventItem: {},
      componentItem: {}, // 事件的所属组件
      currentBlock: {}, // 右侧属性显示的block
      rightLabel: "全局配置", // 右侧标题
      loading: false,
      showVisible: false,
      showCodeContainer: false, // 代码容器
      code: "",
      xml: "",
      displayCode: false,
      displayXml: false,
      options: {
        media: "media/",
        zoom: {
          controls: true,
          wheel: false, // 滚轮控制
          startScale: 1.0,
          maxScale: 3,
          minScale: 0.3,
          scaleSpeed: 1.2,
        },
        grid: {
          spacing: 25,
          length: 3,
          colour: "#ccc",
          snap: true,
        },
        // 最左侧工具栏
        toolbox: `<xml>
          <category name="动作" categorystyle="action_category">
             <block type="open_modal"></block>
             <block type="close_modal"></block>
             <block type="form_validate"></block>
             <block type="form_get_values"></block>
             <block type="form_set_values"></block>
             <block type="form_submit"></block>
             <block type="form_reset"></block>
             <block type="form_add_values"></block>
             <block type="component_display"></block>
             <block type="component_disable"></block>
             <block type="component_required"></block>
             <block type="component_get_select_data"></block>
             <block type="component_assign_query"></block>
             <block type="table_cancel_data"></block>
             <block type="table_set_select"></block>
             <block type="component_reload"></block>
             <block type="component_get_data"></block>
             <block type="component_set_data"></block>
             <block type="request_model"></block>
          </category>
         <category name="文本" colour="%{BKY_TEXTS_HUE}">
            <block type="text"></block>
          </category>
          <category name="变量" custom="VARIABLE" colour="%{BKY_VARIABLES_HUE}">
          </category>
          <category name="内置参数" custom="BUILTIN_PARAM_PALETTE" colour="#808080"/>
          <category name="工具" colour="%{BKY_MATH_HUE}">
           <block type="message_text"></block>
           <block type="message_box"></block>
           <block type="json_generate"></block>
           <block type="console_print"></block>
         </category>
         <category name="函数" colour="290">
            <block type="callback_function_expression"></block>
          </category>
        </xml>`,
      },
    };
  },
  mounted() {},
  methods: {
    open(eventItem = {}, componentItem = {}, callback) {
      // 生成函数的唯一标识
      this.componentItem = { ...componentItem };
      this.eventItem = { ...eventItem };
      this.showGlobal = true;
      this.callback = callback;
      this.showVisible = true;
      this.$nextTick(() => {
        this.initXml(eventItem.eventName);
      });
    },
    initXml(funcName) {
      let initXml;
      const initFlag = !this.eventItem?.eventXml;
      if (initFlag) {
        // 获取事件的参数
        const options = this.eventItem?.event?.options || [];
        let str = "";
        options.forEach((param, index) => {
          str += `<value name="ADD${index + 1}">
            <block type="params_input" id="param${index + 1}${uuid(6)}">
              <field name="CODE">${param}</field>
            </block>
          </value>`;
        });
        initXml = `<xml xmlns="https://developers.google.com/blockly/xml">
  <block type="root_function_expression" id="rootBlock" x="288" y="138">
    <mutation items="${options.length + 1}"></mutation>
    <field name="ROOT_NAME_INPUT">${funcName}</field>
    <value name="ADD0">
      <block type="params_input" id="param0${uuid(
        6
      )}" deletable="false" movable="false" editable="false">
        <field name="CODE">context</field>
      </block>
    </value>
    ${str}
  </block>
</xml>`;
      } else {
        initXml = this.eventItem.eventXml;
        const xml = this.eventItem.eventXml;
        const arr = xml.split('<field name="ROOT_NAME_INPUT">');
        const last = arr[1];
        const index = last.indexOf("</field>");
        const xmlFuncName = last.substring(0, index)?.trim();
        // 如果函数名改变了
        if (xmlFuncName !== funcName) {
          initXml =
            arr[0] +
            '<field name="ROOT_NAME_INPUT">' +
            funcName +
            last.slice(index);
        }
      }
      const xmlRes = Blockly.Xml.textToDom(initXml);
      Blockly.Xml.domToWorkspace(
        xmlRes,
        this.$refs["blocklyComponent"].workspace
      );
    },
    // 将变量声明部分放到函数里面
    getFormatCode() {
      const code = BlocklyJS.workspaceToCode(
        this.$refs["blocklyComponent"].workspace
      );
      const index = code.indexOf("export function");
      const varPart = code.substring(0, index)?.trim();
      const funcPart = code.substring(index);
      const funcIndex = funcPart.indexOf("){") + 2;
      // 将变量声明部分放到函数里面
      return (
        funcPart.slice(0, funcIndex) +
        "\n" +
        "  " +
        varPart +
        funcPart.slice(funcIndex)
      );
    },
    showCode() {
      this.showCodeContainer = true;
      this.displayCode = true;
      this.displayXml = false;
      this.code = this.getFormatCode();
    },
    showXml() {
      this.showCodeContainer = true;
      this.displayCode = false;
      this.displayXml = true;
      const xml = Blockly.Xml.workspaceToDom(
        this.$refs["blocklyComponent"].workspace
      );
      const txt = Blockly.Xml.domToPrettyText(xml);
      this.xml = txt;
      const ws = new Blockly.Workspace();
      Blockly.Xml.domToWorkspace(xml, ws);
    },

    handleSave() {
      const BlocklyComponent = this.$refs.blocklyComponent;
      const validRes = BlocklyComponent.saveWorkspace();
      if (!validRes) return;
      // 校验全局配置
      const rightModel = this.$refs.rightModel;
      const globalValidRes = rightModel.validateGlobal();
      if (!globalValidRes) {
        this.changeShowGlobal(true);
        rightModel.validateGlobal();
        return;
      }
      const data = { ...this.eventItem };
      const xml = Blockly.Xml.workspaceToDom(
        this.$refs["blocklyComponent"].workspace
      );
      data.eventXml = Blockly.Xml.domToPrettyText(xml);
      data.eventJs = this.getFormatCode();
      this.callback(data);
      this.$message.success("操作成功");
    },
    submit() {
      const { code, lang } = this;
      this.showVisible = false;
      this.callback &&
        this.callback({
          code,
          lang,
        });
      this.code = "";
      this.lang = "";
    },
    // 获取当前的积木
    setRightModelBlock(blockData) {
      const type = blockData.type;
      this.currentBlock = blockData;
      // this.$refs.rightModel.init()
      const eventBlocks = ["root_function_expression"];
      const actionBlocks = [
        "open_modal",
        "close_modal",
        "component_disable",
        "component_display",
        "component_required",
        "component_get_select_data",
        "form_submit",
        "form_validate",
        "form_reset",
        "form_get_values",
        "form_set_values",
        "form_add_values",
        "component_assign_query",
        "table_cancel_data",
        "table_set_select",
        "component_reload",
        "component_get_data",
        "component_set_data",
        "message_text",
        "message_box",
        "json_generate",
        "console_print",
        "callback_function_expression",
        "request_model",
      ];
      const textBlocks = ["text"];
      if (eventBlocks.includes(type)) {
        this.showGlobal = false;
        this.rightLabel = "事件配置";
      } else if (actionBlocks.includes(type)) {
        this.showGlobal = false;
        this.rightLabel = "动作配置";
      } else if (textBlocks.includes(type)) {
        this.showGlobal = false;
        this.rightLabel = "动作配置";
      } else {
        this.rightLabel = "全局配置";
        this.showGlobal = true;
      }
    },
    closeCode() {
      this.showCodeContainer = false;
    },
    changeShowGlobal(flag) {
      this.showCodeContainer = false;
      this.showGlobal = flag;
    },
    // 点击积木显示隐藏全局设置
    updateShowGlobal(data) {
      this.showGlobal = data;
    },
    handleCancel() {
      this.showCodeContainer = false;
      this.displayCode = false;
      this.displayXml = false;
      // this.$refs['blocklyComponent']?.workspace?.dispose()
      this.$refs["blocklyComponent"]?.workspace?.clear();
      this.$refs["blocklyComponent"].workspace = null;
      this.showVisible = false;
    },
  },
};
</script>

<style scoped>
.process-design-wrap {
  position: relative;
  height: 100%;
  min-height: calc(90vh - 60px);
}

.reset-drawer ::v-deep .el-drawer__header {
  margin-bottom: 10px !important;
}

#code {
  position: absolute;
  right: 0;
  top: 0;
  width: 35%;
  height: 100%;
  margin: 0;
  z-index: 1000;
  background-color: #f1f1f1;
  overflow: auto;
  padding-left: 10px;
}

#blockly {
  /*position: absolute;*/
  /*z-index: 1000;*/
  /*left: 0;*/
  /*top: 0;*/
  width: 65%;
  height: 100%;
}

.flexcell {
  width: 345px;
  border-top: 1px solid #c6c6c6;
}
</style>
<style>
/*z-index层级问题*/
.blocklyDropDownDiv {
  z-index: 6000 !important;
}

.swal2-container {
  z-index: 6000 !important;
}
</style>
<style>
.create-variable-notification {
  z-index: 9000 !important;
}
</style>
